#include "stdafx.h"
#include "actor.h"

namespace rpg {

	Actor::Actor(const ActorDesc &actorDesc) : LevelObject(actorDesc.levelObjectDesc) {
		mIdleAnimation = NULL;
		mWalkAnimation = NULL;

		mActorNode = actorDesc.ogreSceneNode;
		mActorEntity = static_cast<Ogre::Entity *>(mActorNode->getAttachedObject(0));
		mMaxMoveSpeed = actorDesc.maxMoveSpeed;

		if(actorDesc.idleAnimationName.length() > 0) {
			mIdleAnimation = mActorEntity->getAnimationState(actorDesc.idleAnimationName);

			mIdleAnimation->setLoop(true);
			mIdleAnimation->setTimePosition(0.0);

			safeEnableIdleAnimation(true);
		}

		if(actorDesc.walkAnimationName.length() > 0) {
			mWalkAnimation = mActorEntity->getAnimationState(actorDesc.walkAnimationName);

			mWalkAnimation->setLoop(true);
			mWalkAnimation->setTimePosition(0.0f);

			safeEnableWalkAnimation(false);
		}
	}

	Actor::~Actor(void) {
	}

	void Actor::clearWaypoint(void) {
		mWaypoint.clear();
	}

	void Actor::addPointToWaypoint(const Ogre::Vector3 &point) {
		mWaypoint.push_back(point);
	}

	void Actor::addListToWaypoint(const std::list<Ogre::Vector3> *waypoint) {
		if(waypoint != NULL) {
			mWaypoint.resize(mWaypoint.size() + waypoint->size());
			std::copy(waypoint->begin(), waypoint->end(), mWaypoint.begin());
		}
	}

	bool Actor::isWaypointEmpty(void) const {
		return mWaypoint.empty();
	}

	Ogre::Vector3 Actor::getCurrentMovePoint(void) const {
		Ogre::Vector3 result(Ogre::Vector3::ZERO);

		if(!mWaypoint.empty()) {
			result = mWaypoint.front();
		}

		return result;
	}

	void Actor::update(float deltaTime) {
		Ogre::Vector3 currentPosition = getPosition();
		Ogre::Radian deltaTurn;
		Ogre::Vector3 targetPoint;
		Ogre::Vector3 moveVector;
		Ogre::Vector3 moveVectorNormalized;
		Ogre::Vector3 lookAtPoint;

		if(!mWaypoint.empty()) {
			targetPoint = mWaypoint.front();

			moveVector = targetPoint - currentPosition;
			moveVectorNormalized = moveVector.normalisedCopy();

			lookAtPoint = currentPosition + moveVectorNormalized;

			mActorNode->lookAt(lookAtPoint, Ogre::Node::TS_WORLD, Ogre::Vector3::UNIT_X);

			if(moveVector.length() > 0.1f) {
				currentPosition += moveVectorNormalized * (mMaxMoveSpeed * deltaTime);
			} else {
				currentPosition = targetPoint;
				mWaypoint.pop_front();
			}

			setPosition(currentPosition);
			mActorNode->setPosition(currentPosition);

			safeEnableIdleAnimation(false);
			safeEnableWalkAnimation(true);
		} else {
			safeEnableIdleAnimation(true);
			safeEnableWalkAnimation(false);
		}

		safeIdleAnimationAdvance(deltaTime);
		safeWalkAnimationAdvance(deltaTime);
	}

	void Actor::safeEnableIdleAnimation(bool enable) {
		bool enableState;

		if(mIdleAnimation != NULL) {
			enableState = mIdleAnimation->getEnabled();

			if(enableState != enable) {
				mIdleAnimation->setEnabled(enable);
			}
		}
	}

	void Actor::safeEnableWalkAnimation(bool enable) {
		bool enableState;

		if(mWalkAnimation != NULL) {
			enableState = mWalkAnimation->getEnabled();

			if(enableState != enable) {
				mWalkAnimation->setEnabled(enable);
			}
		}
	}

	void Actor::safeIdleAnimationAdvance(float deltaTime) {
		if(mIdleAnimation != NULL) {
			if(mIdleAnimation->getEnabled()) {
				mIdleAnimation->addTime(deltaTime);
			}
		}
	}

	void Actor::safeWalkAnimationAdvance(float deltaTime) {
		if(mWalkAnimation != NULL) {
			if(mWalkAnimation->getEnabled()) {
				mWalkAnimation->addTime(deltaTime);
			}
		}
	}

}